﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PrearrangedChaos.AgileZen.Service.Model;
using PrearrangedChaos.AgileZen.Service.Rest;

namespace PrearrangedChaos.AgileZen.Service
{
    internal abstract class ZenResourceCollection<TCollection, TModel> : IZenResourceEnumerable<TModel>
        where TModel : IModel
        where TCollection : class, IPagingResponse<TModel>
    {
        private readonly string _apiKey;
        private readonly RestArguments _ids;
        protected bool IsReadonly { get; private set; }

        public ZenResourceCollection(string apiKey, RestArguments ids)
        {
            _apiKey = apiKey;
            _ids = ids;
        }

        public IEnumerator<TModel> GetEnumerator()
        {
            this.IsReadonly = true;
            return new ZenResourceCollectionEnumerator<TCollection, TModel>(_apiKey, this._ids);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        protected void AddEnrichment(string enrichment)
        {
            if (this.IsReadonly)
                throw new EnrichmentNotAppliedException(string.Format(
                    "The enrichment '{0}' connot be applied after collection has been enumerated",
                    enrichment));

            this._ids.AddEnrichment(enrichment);
        }

        protected void SetFilter<TFilter>(Func<TFilter, ZenFilter> filter)
            where TFilter : class, new()
        {
            if (this.IsReadonly)
                throw new FilterNotAppliedException("The filter connot be applied after collection has been enumerated");

            TFilter projectFilter = new TFilter();

            this._ids.Filter = filter.Invoke(projectFilter).GetExpression();
        }
    }
}
